package BehaviorPattern.Observer;

/**
 * @author: Themberfue
 * @date: 2025/8/13 11:59
 * @description:
 */
import java.util.ArrayList;
import java.util.List;

// 1. 观察者接口
interface Observer {
    // 接收更新的方法，参数为气象数据
    void update(float temperature, float humidity, float pressure);
}

// 2. 主题接口
interface Subject {
    // 注册观察者
    void registerObserver(Observer o);
    // 移除观察者
    void removeObserver(Observer o);
    // 通知所有观察者
    void notifyObservers();
}

// 3. 具体主题：气象站
class WeatherStation implements Subject {
    private List<Observer> observers; // 观察者列表
    private float temperature;       // 温度
    private float humidity;          // 湿度
    private float pressure;          // 气压

    public WeatherStation() {
        observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    @Override
    public void notifyObservers() {
        // 通知所有观察者
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    // 气象数据更新时调用此方法
    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged(); // 数据变化，通知观察者
    }

    // 数据变化的处理
    private void measurementsChanged() {
        notifyObservers();
    }
}

// 4. 具体观察者：当前天气显示
class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;
    private Subject weatherStation; // 保存主题引用，便于取消订阅

    public CurrentConditionsDisplay(Subject weatherStation) {
        this.weatherStation = weatherStation;
        weatherStation.registerObserver(this); // 注册为观察者
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display(); // 收到更新后显示
    }

    // 显示当前天气
    public void display() {
        System.out.println("当前天气: " + temperature + "°C, 湿度: " + humidity + "%");
    }
}

// 4. 具体观察者：统计数据显示
class StatisticsDisplay implements Observer {
    private float maxTemp = 0.0f;
    private float minTemp = Float.MAX_VALUE;
    private float tempSum = 0.0f;
    private int numReadings;

    public StatisticsDisplay(Subject weatherStation) {
        weatherStation.registerObserver(this); // 注册为观察者
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        tempSum += temperature;
        numReadings++;

        maxTemp = Math.max(maxTemp, temperature);
        minTemp = Math.min(minTemp, temperature);

        display(); // 收到更新后显示统计数据
    }

    public void display() {
        System.out.println("温度统计: 平均 " + (tempSum / numReadings) + "°C, 最高 " + maxTemp + "°C, 最低 " + minTemp + "°C");
    }
}

// 4. 具体观察者：预报显示
class ForecastDisplay implements Observer {
    private float lastPressure;
    private float currentPressure;

    public ForecastDisplay(Subject weatherStation) {
        weatherStation.registerObserver(this); // 注册为观察者
        currentPressure = 29.92f; // 初始气压
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        lastPressure = currentPressure;
        currentPressure = pressure;
        display(); // 收到更新后显示预报
    }

    public void display() {
        System.out.print("天气预报: ");
        if (currentPressure > lastPressure) {
            System.out.println("天气将转好！");
        } else if (currentPressure == lastPressure) {
            System.out.println("天气保持不变");
        } else {
            System.out.println("可能会下雨！");
        }
    }
}

// 5. 客户端代码
public class ObserverExample {
    public static void main(String[] args) {
        // 创建主题：气象站
        WeatherStation weatherStation = new WeatherStation();

        // 创建观察者并注册
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherStation);
        StatisticsDisplay statsDisplay = new StatisticsDisplay(weatherStation);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherStation);

        // 模拟气象数据更新
        System.out.println("\n=== 第一次数据更新 ===");
        weatherStation.setMeasurements(25.6f, 65f, 1013.1f);

        System.out.println("\n=== 第二次数据更新 ===");
        weatherStation.setMeasurements(26.3f, 62f, 1012.9f);

        System.out.println("\n=== 第三次数据更新 ===");
        weatherStation.setMeasurements(24.8f, 70f, 1012.5f);

        // 移除一个观察者
        weatherStation.removeObserver(forecastDisplay);
        System.out.println("\n=== 移除预报显示后的数据更新 ===");
        weatherStation.setMeasurements(25.1f, 68f, 1013.0f);
    }
}

